﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ThreeByte.ActiveDeck.Config;
using System.Xml.Linq;
using ThreeByte.Media;
using log4net;
using System.IO;
using ThreeByte.ActiveDeck.Controls;
using ThreeByte.ActiveDeck.AddIn.Content.Controls;
using ThreeByte.ActiveDeck.AddIn.Config;
using System.Text.RegularExpressions;

namespace ThreeByte.ActiveDeck.Content
{
    /// <summary>
    /// Interaction logic for NavigatorPreview.xaml
    /// </summary>
    public partial class NavigatorPreview : UserControl, IPreviewControl
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(NavigatorPreview));

        private NavigatorConfig _config;
        public PageConfig Config { get; set; }

        public NavigatorPreview(NavigatorConfig config) {
            InitializeComponent();
            _config = config;
            Config = config;
            DataContext = config;

            //Refresh the collection of displayed objects
            //foreach(DesignerControl d in config.Elements) {
            //    ThreeByte.Controls.DesignerCanvas parent = VisualTreeHelper.GetParent(d) as ThreeByte.Controls.DesignerCanvas;
            //    if(parent != null) {
            //        parent.Children.Remove(d);
            //    }
            //    DesignSurface.Children.Add(d);
            //}
        }

        public PresentationPageConfiguration GetPageConfiguration() {
            XNamespace ns = Service.ServiceConfiguration.NAMESPACE;

            PresentationPageConfiguration newPage = new PresentationPageConfiguration();

            XElement pageNode = _config.GetPresentationXml("NavigatorSlide");

            XElement viewportNode = new XElement(ns + "Viewport");
            viewportNode.Add(new XAttribute("Width", _config.NavigatorWidth));
            viewportNode.Add(new XAttribute("Height", _config.NavigatorHeight));
            viewportNode.Add(new XAttribute("HorizontalOffset", _config.OffsetX));
            viewportNode.Add(new XAttribute("VerticalOffset", _config.OffsetY));
            viewportNode.Add(new XAttribute("ZoomEnabled", _config.ZoomEnabled));

            if(_config.Background != null) {
                newPage.Resources[_config.Background.ID] = _config.Background;
                XElement backgroundNode = new XElement(ns + "BackgroundImage", new XAttribute("ResourceID", _config.Background.ID));
                viewportNode.Add(backgroundNode);
            }

            foreach(DesignerControl d in _config.Elements) {
                viewportNode.Add(d.GetPresentationXml());
                foreach(VideoResource v in d.GetMediaResources()) {
                    newPage.MediaResources[v.ID] = v;
                }
                foreach(GraphicResource g in d.GetGraphicResources()) {
                    newPage.Resources[g.ID] = g;
                }
            }

            pageNode.Add(viewportNode);

            int i = 1;
            foreach(LayerConfig layer in _config.Layers){
                layer.Refresh(false); //Update from the Presentation slides
                //Add the Overlay elements
                XElement layerNode = new XElement(ns + "Layer");
                layerNode.Add(new XAttribute("ID", i++));
                layerNode.Add(new XAttribute("Name", layer.Name));
                layerNode.Add(new XAttribute("Enabled", layer.Show));
                layerNode.Add(new XAttribute("AutoHide", !(layer.Pinned)));
                if(layer.Condition != null) {
                    layerNode.Add(new XAttribute("Condition", layer.Condition));
                }
                PixelSpace boundingBox = layer.GetBoundingBox(Config.LayoutOrientation);
                PixelTranslator offset = new PixelTranslator() { XOffset = -1 * boundingBox.X, YOffset = -1 * boundingBox.Y };

                layerNode.Add(new XAttribute("Top", boundingBox.Y));
                layerNode.Add(new XAttribute("Left", boundingBox.X));
                layerNode.Add(new XAttribute("Height", boundingBox.H));
                layerNode.Add(new XAttribute("Width", boundingBox.W));

                foreach(DesignerControl d in layer.Elements) {
                    layerNode.Add(d.GetPresentationXml(offset));
                    foreach(VideoResource v in d.GetMediaResources()) {
                        newPage.MediaResources[v.ID] = v;
                    }
                    foreach(GraphicResource g in d.GetGraphicResources()) {
                        newPage.Resources[g.ID] = g;
                    }
                }
                pageNode.Add(layerNode);
            }
            
            newPage.ConfigXml = pageNode;
            return newPage;
        }

        private void LayoutRoot_DragEnter(object sender, DragEventArgs e) {
            log.Debug("Drag Enter");
            e.Effects = DragDropEffects.Link;
        }

        private void LayoutRoot_DragLeave(object sender, DragEventArgs e) {

        }

        private void LayoutRoot_DragOver(object sender, DragEventArgs e) {
            e.Effects = DragDropEffects.Link;
        }

        private static PixelScaler DefaultPixelScaler = new PixelScaler() { XScale = (100.0 / 72.0), YScale = (100.0 / 72.0) };

        private void LayoutRoot_Drop(object sender, DragEventArgs e) {
            log.Debug("Drop");

            try {
                string[] formats = e.Data.GetFormats();
                int i = 0;
                foreach(string s in formats) {
                    log.DebugFormat("Format [{0}]: {1}", i++, s);
                }

                Point dropPoint = e.GetPosition(DraggableSurface);

                //If FileDrop is exposed, then look at the extension
                if(formats.Any(p => (p == DataFormats.FileDrop))) {
                    string path = ((string[])(e.Data.GetData(DataFormats.FileDrop)))[0];
                    string extension = System.IO.Path.GetExtension(path).ToLower();

                    //Get Mouse position of drop and insert there
                    
                    dropPoint.X += DraggableSurface.HorizontalOffset;
                    dropPoint.Y += DraggableSurface.VerticalOffset;

                    if(extension == @".png"
                        || extension == @".jpg"
                        || extension == @".jpeg") { // Try to parse as an image
                        //Parse as an image
                        DesignerButton newButton = DesignerButton.CreateFromImageFile(path, dropPoint);
                        _config.Elements.Add(newButton);
                        //DesignSurface.Children.Add(newButton);

                    } else if(extension == @".mov") {  // Try to parse as a video
                        //Parse as a video
                        //MemoryStream memStream = (MemoryStream)(e.Data.GetData(DataFormats.FileDrop));
                        //Open the video file

                        //Grab a thumbnail for positioning


                        //Encode and store in the file format
                        //MediaPlayer.Source = new Uri(path);

                        //MediaElement newMediaElement = new MediaElement();
                        //newMediaElement.Source = new Uri(path);
                        //DesignerControl dControl = new DesignerControl(newMediaElement, new PixelSpace() { W = 150, H = 100, X = 100, Y = 100 });
                        string pathRoot = Config.ParentSlideConfig.Parent.GetPresentationPath();
                        DesignerVideo dControl = DesignerVideo.CreateFromMediaFile(path, pathRoot, dropPoint);

                        _config.Elements.Add(dControl);
                        //DesignSurface.Children.Add(dControl);
                        //Canvas.SetLeft(dControl, 0.0);
                        //Canvas.SetTop(dControl, 0.0);



                    } 

                    //} else if(formats.Any(p => (p == @"PowerPoint 14.0 Slides Package"))) {

                    //    //Return Active Slide Range

                    //    Microsoft.Office.Interop.PowerPoint.SlideRange slideRange = Globals.ThisAddIn.Application.ActiveWindow.Selection.SlideRange;
                    //    log.DebugFormat("Slide Count: {0} ID:{1} Index:{2} ", slideRange.Count, slideRange.SlideID, slideRange.SlideIndex);

                    //    //Make sure it is only one slide
                    //    if(slideRange.Count != 1) {
                    //        log.Info("Cannot use more than one slide");
                    //        return;
                    //    }
                    //    List<Microsoft.Office.Interop.PowerPoint.Shape> shapesToShow = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
                    //    List<DesignerControl> controlsToAdd = new List<DesignerControl>();
                    //    foreach(Microsoft.Office.Interop.PowerPoint.Shape s in slideRange.Shapes) {
                    //        string pageLink = s.Tags[ObjectTags.PAGE_LINK];
                    //        if(!(string.IsNullOrEmpty(pageLink))){
                    //            int pageLinkNumber = int.Parse(pageLink);
                    //            log.InfoFormat("Found an interactive element: {0} - [{1}]", s.Type, pageLinkNumber);

                    //            try {
                    //                //Create temporary file
                    //                string filePath = System.IO.Path.GetTempFileName();

                    //                s.Export(filePath, Microsoft.Office.Interop.PowerPoint.PpShapeFormat.ppShapeFormatPNG);
                    //                PixelSpace pos = new PixelSpace() { H = (int)(s.Height), W = (int)(s.Width), X = (int)(s.Left), Y = (int)(s.Top) };
                    //                pos = DefaultPixelScaler.Scale(pos);
                    //                GraphicResource newLinkResource = new GraphicResource(string.Format("PageLinkButton_{0}", pageLinkNumber), new Uri(filePath), ImageType.PNG);

                    //                //Create the Link Button
                    //                DesignerControl newInteractiveControl = new DesignerButton(newLinkResource, pos) {
                    //                                                            Action = new NavigationAction() {
                    //                                                                Jump = true,
                    //                                                                Page = pageLinkNumber
                    //                                                            }
                    //                                                        };
                    //                controlsToAdd.Add(newInteractiveControl);  //Defer adding them so they end up on top

                    //                //Delete the file
                    //                File.Delete(filePath);
                    //            } catch(Exception ex) {
                    //                log.Error("Cannot export shape type", ex);
                    //            }
                    //            shapesToShow.Add(s);
                    //            s.Visible = Microsoft.Office.Core.MsoTriState.msoFalse;
                    //        }
                    //    }

                    //    //Remove all objects currently on the page
                    //    _config.Elements.Clear();
                    //    DesignSurface.Children.Clear();

                    //    GraphicResource newResource = new GraphicResource(SlideUtil.Snapshot(slideRange), string.Format("SlideSnapshot_{0}", slideRange.SlideID), ImageType.JPEG);
                    //    DesignerControl dControl = new DesignerImage(newResource);
                    //    _config.Elements.Add(dControl);
                    //    DesignSurface.Children.Add(dControl);

                    //    foreach(DesignerControl c in controlsToAdd) {
                    //        _config.Elements.Add(c);
                    //        DesignSurface.Children.Add(c);
                    //    }

                    //    //Make shapes visible again.
                    //    foreach(Microsoft.Office.Interop.PowerPoint.Shape s in shapesToShow) {
                    //        s.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
                    //    }

                    //} else if(formats.Any(p => (p == @"System.Windows.Controls.Button"))) {
                    //    //Drop a new button on to the designer canvas
                    //    ActionButton newActionButton = new ActionButton();

                    //    DesignerControl dControl = new DesignerControl(newActionButton, new PixelSpace() { W = 150, H = 40, X = 300, Y = 300 });
                    //    DesignSurface.Children.Add(dControl);
                    //    _config.Elements.Add(dControl);
                    //}
                } else if(formats.Any(p => (p == DataFormats.Text))) {
                    string droppedUrl = e.Data.GetData(DataFormats.Text, true).ToString();

                    Regex reg = new Regex(@"(http(s)?://)?([\w-]+\.)+[\w-]+(/[\w- ;,./?%&=]*)?");

                    if(reg.IsMatch(droppedUrl)) {
                        PixelSpace webViewSpace = new PixelSpace() { X = (int)Math.Round(dropPoint.X), Y = (int)Math.Round(dropPoint.Y), W = 200, H = 200 };
                        DesignerWebView webView = new DesignerWebView(droppedUrl, webViewSpace);

                        _config.Elements.Add(webView);
                    } else {
                        log.InfoFormat("Not a URL");

                    }
                }

                //object o = e.Data.GetData("Object Descriptor");

                //log.Info("Inspect:" + o);
                //log.InfoFormat("Properties DPI:{0}, Width:{1}, Decode:{2}", newBitmap.DpiX, newBitmap.PixelWidth, newBitmap.DecodePixelWidth);

            } catch(Exception ex) {
                log.Fatal("Collossal Fail", ex);
            }
        }

        private void DesignSurface_ItemDeleted(object sender, ThreeByte.Controls.ItemDeletedEventArgs e) {
            DesignerControl deletedItem = e.Item as DesignerControl;
            if(deletedItem != null) {
                _config.Elements.Remove(deletedItem);
            }
        }

        private void DesignSurface_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            log.DebugFormat("Selection Changed: {0}", e.AddedItems);

            //Get the selected item
            DesignerButton control = DesignSurface.SelectedItem as DesignerButton;
            if(control != null) {
                //Update the currenlty shown object in the property pane.
                Globals.ThisAddIn.GetPropertiesControl().Show(control);
            }
            DesignerImage image = DesignSurface.SelectedItem as DesignerImage;
            if(image != null) {
                Globals.ThisAddIn.GetPropertiesControl().Show(image);
           }

        }
    }
}
